<?php

class Vega_App
{
    protected static $_instance = null;
    
    protected $_rootPath = null;
    protected $_appName = 'default';
    
    protected $_loader = null;
    
    
    protected $_request = null;
    protected $_response = null;
    
    protected $_currentModule = null;
    protected $_currentModuleClass = '';

	/*
	 * Language name
	 */
	public $_language = null;
	        
    public $coreConfig = array();
    
    protected $_useWebDebug = true;
        
    public static function getInstance()
    {
        if (null === self::$_instance)
        {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    
    protected function __construct()
    {
        require_once 'Vega/Loader.php';
        $this->_loader = new Vega_Loader();
        
        require_once 'Vega/Request.php';
        $this->_request = new Vega_Request();
        
        require_once 'Vega/Response.php';
        $this->_response = new Vega_Response();
        
    }
    
    
    /**
     * Returns the request object or request value
     *
     * @return Vega_Request
     */
    public function getRequest($key = null, $default=null)
    {
		if (null != $key && null != $this->_request)
			return $this->_request->getRequest($key, $default);
		else
			return $this->_request;
    }
    
    /**
     * Returns the response object
     *
     * @return Vega_Response
     */
    public function getResponse()
    {
        return $this->_response;
    }
    
    
    /**
     * Returns the loader
     *
     * @return Vega_Loader
     */
    public function getLoader()
    {
        return $this->_loader;
    }
    
    /**
     * Sets up framework
     *
     * @param unknown_type $path
     * @return unknown
     */
    public function setup($path)
    {
        $this->_rootPath = $path;
        $this->_loader->setRootPath($path);
        return $this;
    }
    
    /**
     * Sets up application
     *
     * @param string $appName - Application name
     * @return Vega_App
     */
    public function setupApp($appName = 'default')
    {
        $this->_appName = $appName;
        
		$appPath = $this->_rootPath . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . $appName;
		if (!defined('APP_PATH')) define('APP_PATH', $appPath);
        $this->_loader->setAppPath($appPath);
        
        $this->_loader->setDir('config', 'config');
        $this->coreConfig = $this->loadConfig('core');

        return $this;
    }
    
    /**
     * Get application name
     *
     * @return string
     */
    public function getAppName()
    {
        return $this->_appName;
    }
    
    /**
     * Get application path
     *
     * @return string
     */
    public function getAppPath()
    {
        return $this->_loader->getAppPath();
    }
    
    /**
     * Get the framework path
     *
     * @return string
     */
    public function getRootPath()
    {
        return $this->_rootPath;
    }
    
    /**
     * Returns current module object
     *
     * @return Vega_Module
     */
    public function getCurrentModule()
    {
        return $this->_currentModule;
    }

   /**
     * Loads module/action object
     * 
     * First, check the existent of the action class file in /modules/<Module Name>/actions
     * If it does not exist, then check the module class in /modules/<Module Name>/actions.php
     * If fail to load a module/action class, return FALSE.
     *
     * @param Vega_Request $request
     */
    public function loadModule($request, $response)
    {
        $module = $request->getModuleName();
        $action = $request->getActionName();

        $this->_loader->setDir('module', 'modules' . DIRECTORY_SEPARATOR . $module);

        $objectType = $className = null;

        $filepath = $this->_loader->getPath('module', 'actions' . DIRECTORY_SEPARATOR . $action . '.action.php');
        
        if (file_exists($filepath))
        {
            $className  = ucfirst($action) . 'Action';
        }
        else
        {
            $filepath = $this->_loader->getPath('module', 'actions.php');
            
            if (!file_exists($filepath))
            {
                return false;
            }
            $className  = ucfirst($module) . 'Module';
        }

        // if the class name is the same with current module class name
        // the returns the current module object.
        //
        // This happens when an action is forwarded by another action in the same Vega_Module class
        // It can be better if we have a stack to save all loaded module objects. But that solution eat more RAM
        // and doesn't happen usually.
        if ($className == $this->_currentModuleClass)
        {
            return $this->_currentModule;
        }

        $object = $this->_initModuleObject($filepath, $className);
        
        return $object;
    }

    /**
     * Init a Vega_Module object
     *
     * @param string $filePath
     * @param string $className
     * @return Vega_Module
     */
    protected function _initModuleObject($filepath, $className)
    {
        $this->_loader->loadAbsolutePath($filepath);

        if (!class_exists($className))
        {
            return false;
        }

        $object = new $className($this);
        $this->_currentModule = $object;
        $this->_currentModuleClass = $className;
        return $object;
    }
    
    /**
     * Loads widget
     *
     * @param string $widget
     * @param array $params Parameters passed by View
     * @return mixed
     */
    
    public function loadWidget($widget, array $params)
    {
        $widget = strtolower($widget);
        $this->_loader->setDir('widget', 'widgets' . DIRECTORY_SEPARATOR . $widget);
        
        $filepath =  $this->_loader->getPath('widget', $widget . '.widget.php');
        
        if (!file_exists($filepath))
        {
            return false;
        }
        
        require_once $filepath;
        
        $widgetClass = ucfirst($widget) . 'Widget';
        
        if (!class_exists($widgetClass))
        {
            //echo $widgetClass;
            return false;
        }
        
        return new $widgetClass($this, $params);
    }
    
    /**
     * Loads configuration data from a config file
     *
     * @param string $file
     * @param string $varname
     * @return mixed
     */
    public function loadConfig($file, $varname = 'config')
    {
        if (!$varname || !is_string($varname))
        {
            $varname = 'config';
        }
        
        $config = $this->_loader->load('config', $file . '.config.php', $varname);
        return $config;
    }
    /*
     * Get WebDebug Config
     */
    public function getWebDebugConfig()
    {
    	return $this->_useWebDebug;
    }
    /**
     * Enable Webdebug
     */
    public function enableWebDebug()
    {
    	$this->_useWebDebug = true;
    }
    /*
     * Disable WebDebug
     */
    public function disableWebDebug()
    {
    	$this->_useWebDebug = false;
    }
	
	private $_lockFile = '';
	
	
	public function beginThread($threadName) {
		
		if ($threadName != '') $this->_appName = $threadName;
		
		$lockFile = $this->_rootPath . DIRECTORY_SEPARATOR.'cronjobs'. DIRECTORY_SEPARATOR.$this->_appName.'.lock';
		
		$this->_lockFile = $lockFile;
		if (!file_exists($this->_lockFile)) {
			try {
				$handle = fopen($this->_lockFile, "w+");
				fclose($handle);
			}
			catch (Exception $e) {
				echo $e->getMessage();
			}
		}
		else 
			die ('Another instance is already running');
	}
	
	public function endThread() {
		if ($this->_lockFile != null)
			try {
				unlink($this->_lockFile);
			}
			catch (Exception $e) {
				echo $e->getMessage();
			}
	}

}